<template>
  <!-- 打印按钮 -->
  <div class="BasePrintButton-container" :style="{ display: showTextLoading ? 'inline-block' : 'block' }">
    <a-button v-show="false" :id="printBtnId" v-print="printOption" />
    <component :is="buttonType" :type="type" :loading="loadingState.isPrint && innerSpinning" @click="handleClick">
      <a-spin v-if="showTextLoading" :spinning="loadingState.isPrint && innerSpinning" />
      <span>{{ buttonText }}</span>
    </component>
    <div class="print-wrapper">
      <div v-if="useComponent" :id="printOption.id">
        <component :is="useComponent" ref="printComponent" v-bind="componentQuery" />
      </div>
      <div :id="printOption.id" v-html="filterIllegalChar(realPrintContent) "></div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'BasePrintButton',
  props: {
    // 需要打印的内容，为完整的html字符串文本
    printContent: {
      type: String,
      default: ''
    },
    // 调用打印前回调函数，该函数返回一个Promise实例，取该Promise完成后的值作为打印内容(即then所返回的值)
    beforePrintFn: {
      type: [Function],
      default: null
    },
    // 按钮样式类型 'default' | 'primary'
    type: {
      type: String,
      default: 'default'
    },
    // 按钮组件类型，默认为<a-button />， 如果需要在列表显示可以传入'a'设置为 <a/>
    buttonType: {
      type: String,
      default: 'aButton'
    },
    // 按钮文本内容
    buttonText: {
      type: String,
      default: '打印'
    },
    // 是否显示分割线，在buttonType不是'aButton'的情况下，默认显示
    showDivider: {
      type: Boolean,
      default: true
    },
    // 扩展选项值，同vue-print-nb的API
    // standard: Document type, default is html5, optional html5, loose, strict
    // extraHead: Additional tags attached to the head tag, separated by commas
    // extraCss: Additional link connections, separated by commas
    // popTitle: Title shows the title
    // endCallback(): Callback events after printing
    extraOptions: {
      type: Object,
      default() {
        return {}
      }
    },
    useComponent: {
      type: [Object],
      default() {
        return null
      }
    },
    componentQuery: {
      type: Object,
      default() {
        return {}
      }
    },
    params: {
      type: Object,
      default() {
        return {}
      }
    },
    //点击打印按钮左侧是否显示loadding效果
    innerSpinning: {
      type: Boolean,
      default: true
    }
  },
  computed: {
    showTextLoading() {
      return this.buttonType !== 'aButton'
    }
  },
  watch: {
    extraOptions: {
      immediate: true,
      deep: true,
      handler(val) {
        try {
          this.printOption = {
            ...this.printOption,
            ...val
          }
        } catch (e) {
          console.error('PrintError：', e)
        }
      }
    },
    printContent: {
      immediate: true,
      handler(val) {
        this.realPrintContent = val
      }
    },
    'loadingState.isPrint': {
      handler: function (val) {
        this.$emit("getLoadedState", val)
      },
      deep: true
    }
  },
  data() {
    return {
      printBtnId: '', // 打印按钮的ID
      // 参数见 vue-print-nb
      printOption: {
        id: 'printBox',
        extraCss: '',
      },
      realPrintContent: '', // 实际的打印内容
      loadingState: {
        isPrint: false
      }
    }
  },
  created() {
    this.initDomId()
  },
  methods: {
    /**
     * 过滤非法字符（部分打印表解析出非法的样式，在这里将其置空）
     */
    filterIllegalChar(str) {
      return str && str?.replace('font-family:等线;', '')
    },
    /**
     * 根据组件ID,生成打印按钮的dom ID,避免同一页面多个打印按钮冲突问题
     */
    initDomId() {
      this.printOption.id = `printBox-${this._uid}`
      this.printBtnId = `printBtn-${this._uid}`
    },
    /**
     * 触发打印
     */
    triggerPrint() {
      console.log(this.printBtnId,"====434464")
      const dom = document.querySelector(`#${this.printBtnId}`)
      dom.click()
    },
    async handleClick() {
      if (this.loadingState.isPrint) {
        return
      }
      this.loadingState.isPrint = true
      // 如果使用组件的话，则需要组件实现 getPrintContent 方法，同时该方法返回一个Promise实例
      if (this.useComponent) {
        this.$refs.printComponent &&
          this.$refs.printComponent
            .getPrintContent()
            .then(() => {
              this.triggerPrint()
              this.loadingState.isPrint = false
            })
            .catch(() => {
              his.loadingState.isPrint = false
            })
        return
      }
      // 调用打印前回调函数，该函数返回一个Promise实例，取该Promise完成后的值作为打印内容(即then所返回的值)
      if (this.beforePrintFn) {
        try {
          const params = this.params
          const res = await this.beforePrintFn(params)
          this.realPrintContent = res
          this.triggerPrint()
        } catch (e) {
          console.error(e)
        }
      } else {
        this.triggerPrint()
      }
      this.loadingState.isPrint = false
    }
  }
}
</script>
<style>
/* 隐藏页眉页脚 */
@page {
  size: auto;
  margin: 0mm;
}

@media print{
  body {
    /* 解决打印时会多出一页空白页的问题 */
    height: auto !important;
  }
}

table {
  margin-right: auto;
  margin-left: auto;
}
</style>
<style lang="less" scoped>
.BasePrintButton-container {
  position: relative;

  .print-wrapper {
    display: none;
  }
}
</style>